<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// | 该文件的开源协议以所在项目的LICENSE文件为准，请遵守开源协议要求
// +----------------------------------------------------------------------
// | 账户资产
// +----------------------------------------------------------------------
namespace app\finance\model;

use Inphp\Core\Db\Db;
use Inphp\Core\Db\PDO\Model;
use Inphp\Core\Modules;

class BalanceModel extends Model
{
    /**
     * 主表名
     * @var string
     */
    protected string $tableName = "finance_balance";

    /**
     * 主键
     * @var string
     */
    protected string $primaryKey = "uid";

    /**
     * 资产名称列表
     * @return string[]
     */
    public static function names(): array
    {
        $list = getFinanceConfig("balance.list");
        return empty($list) ? ["balance" => "余额", "integral" => "积分"] : $list;
    }

    /**
     * 获取余额
     * @param int $uid
     * @return array
     */
    public static function getBalance(int $uid): array
    {
        $item = self::getRowByPrimaryKey($uid);
        if (empty($item) && $uid > 0) {
            self::emptyQuery()
                ->insert(["uid" => $uid]);
        }
        $balance = self::processBalance($item);
        //查询正在退款
        $refund = Db::from("finance_balanceRefund")->where("uid", $uid)->where("state", 2)->orderBy("id", "desc")->first();
        $balance["refund"] = !empty($refund) ? $refund : ["id" => 0, "amount" => "0.00"];
        //余额要扣减
        $balance["balanceTotal"] = max(bcsub($balance["balance"], bcsub($balance["refund"]["amount"], $balance["refund"]['amount'], 2), 2), 0);
        return $balance;
    }

    /**
     * 处理钱包数据
     * @param ?array $row
     * @return array
     */
    public static function processBalance(?array $row = []): array
    {
        $list = Modules::getModule("finance")->getConfig("balance");
        $walletNames = $list["list"] ?? [];
        $decimal = $list["decimal"] ?? [];
        $decimal = !empty($decimal) ? $decimal : [];
        $wallet = [];
        foreach ($walletNames as $key=>$name){
            $wallet[$key] = $row[$key] ?? 0;
            //处理小数点
            $dec = $decimal[$key] ?? 2;
            $dec = $dec > 0 ? $dec : 0;
            $wallet[$key] = $dec > 0 ? sprintf("%.{$dec}f", $wallet[$key]) : floor($wallet[$key]);
        }
        return $wallet;
    }

    /**
     * 增加余额
     * @param int $uid
     * @param string $balanceName
     * @param float|int $amount
     * @param string $code
     * @param string|null $log
     * @param string|null $linkId
     * @param int $editor
     * @return bool
     */
    public static function plus(int $uid, string $balanceName, float|int $amount, string $code, string $log = null, string $linkId = null, int $editor = 0): bool
    {
        $config = Modules::getModule("finance")->getConfig();
        if (!isset($config["balance"]["list"][$balanceName])) {
            return false;
        }
        $decimal = $config["balance"]["decimal"][$balanceName] ?? 2;
        $balance = self::getBalance($uid);
        $nowBalance = $balance[$balanceName] ?? 0;
        $lastBalance= bcadd($nowBalance, $amount, $decimal);
        //记录
        Db::begin();
        $m = new BalanceHistoryModel();
        $data = [
            "uid"       => $uid,
            "name"      => $balanceName,
            "amount"    => $amount,
            "balance"   => $lastBalance,
            "code"      => $code,
            "log"       => $log,
            "editor"    => $editor,
            "linkId"    => $linkId
        ];
        foreach ($data as $key => $val) {
            $m->{$key} = $val;
        }
        if (!$m->save()) {
            Db::rollback();
            return false;
        }
        if (!self::emptyQuery()
            ->where("uid", $uid)
            ->increment($balanceName, $amount)
            ->update()) {
            Db::rollback();
            return false;
        }
        Db::commit();
        return true;
    }
    public static function minus(int $uid, string $balanceName, float|int $amount, string $code, string $log = null, string $linkId = null, int $editor = 0): bool
    {
        return self::plus($uid, $balanceName, -$amount, $code, $log, $linkId, $editor);
    }
    public static function increment(int $uid, string $balanceName, float|int $amount, string $code, string $log = null, string $linkId = null, int $editor = 0): bool
    {
        return self::plus($uid, $balanceName, $amount, $code, $log, $linkId, $editor);
    }
    public static function decrement(int $uid, string $balanceName, float|int $amount, string $code, string $log = null, string $linkId = null, int $editor = 0): bool
    {
        return self::minus($uid, $balanceName, $amount, $code, $log, $linkId, $editor);
    }
}